#ifndef __CLINESEGMENT3D_H__
#define __CLINESEGMENT3D_H__

#include "StdDefs.h"
#include "CMathFixed.h"
#include "CVector3d.h"


// CLineSegment3d* must maintain casting ability with (fixed*).
// CLineSegment3d may not have virtuals, inherited, or instantiated data.
 

class CLineSegment3d
{
public:
	CLineSegment3d(){}
	CLineSegment3d( const fixed* ijk );
	CLineSegment3d( fixed v0i, fixed v0j, fixed v0k, fixed v1i, fixed v1j, fixed v1k );
	CLineSegment3d( const CVector3d* v );
	CLineSegment3d( const CVector3d& v0, const CVector3d& v1 ); 
	~CLineSegment3d(){}

	static fixed		ClosestPoint( const CVector3d& v0, const CVector3d& v1,
									  const CVector3d& point, CVector3d& closestPoint );

	static boolean		Intersects( const CVector3d& seg0V0, const CVector3d& seg0V1,
									const CVector3d& seg1V0, const CVector3d& seg1V1,
									fixed* u0, fixed *u1 );

	static CVector3d&	ShortestVectorToPoint( const CVector3d& v0, const CVector3d& v1,
											   const CVector3d& point,
											   CVector3d& v, fixed& u );

	static void			ShortestVectorToSegment( const CVector3d& seg0V0, const CVector3d& seg0V1,
												 const CVector3d& seg1V0, const CVector3d& seg1V1,
												 CVector3d& c1, CVector3d& c2, fixed* u0 = NULL, fixed *u1 = NULL );

	fixed				ClosestPoint( const CVector3d& point, CVector3d& closestPoint ) const;

	CVector3d&			ShortestVectorToPoint( const CVector3d& point, CVector3d& v, fixed& u ) const;

	void				ShortestVectorToSegment( const CLineSegment3d& s2, CVector3d& c1, CVector3d& c2, fixed* u0 = NULL, fixed *u1 = NULL ) const;

	boolean				Intersects( const CLineSegment3d& seg, fixed* uThis, fixed *uSeg ) const;

	CLineSegment3d&		operator=( const fixed* ijk ); 
	CLineSegment3d&		operator=( const CVector3d* v );

	fixed&				operator[]( uint32 idx );

	CVector3d			m_v0;
	CVector3d			m_v1;
};





inline
CLineSegment3d::CLineSegment3d( const fixed* ijk )
{ 
	m_v0.m_i = *ijk; 
	m_v0.m_j = *( ijk + 1 );
	m_v0.m_k = *( ijk + 2 );
	m_v1.m_i = *( ijk + 3 ); 
	m_v1.m_j = *( ijk + 4 );
	m_v1.m_k = *( ijk + 5 );
}


inline
CLineSegment3d::CLineSegment3d( fixed v0i, fixed v0j, fixed v0k, fixed v1i, fixed v1j, fixed v1k )
{ 
	m_v0.m_i = v0i; 
	m_v0.m_j = v0j;
	m_v0.m_k = v0k;
	m_v1.m_i = v1i; 
	m_v1.m_j = v1j;
	m_v1.m_k = v1k;
}


inline 
CLineSegment3d::CLineSegment3d( const CVector3d* v )
{ 
	m_v0 = *v; 
	m_v1 = *( v + 1 ); 
}


inline 
CLineSegment3d::CLineSegment3d( const CVector3d& v0, const CVector3d& v1 )
{ 
	m_v0 = v0; 
	m_v1 = v1; 
}


inline
fixed CLineSegment3d::ClosestPoint( const CVector3d& point, CVector3d& closestPoint ) const
{
	return ClosestPoint( m_v0, m_v1, point, closestPoint );
}


inline
boolean	CLineSegment3d::Intersects( const CLineSegment3d& seg, fixed* uThis, fixed *uSeg ) const
{
	return Intersects( m_v0, m_v1, seg.m_v0, seg.m_v1, uThis, uSeg );
}


inline
CVector3d& CLineSegment3d::ShortestVectorToPoint( const CVector3d& point,
												  CVector3d& v, fixed& u ) const
{
	return ShortestVectorToPoint( m_v0, m_v1, point, v, u );
}


inline
void CLineSegment3d::ShortestVectorToSegment( const CLineSegment3d& s2, CVector3d& c1, CVector3d& c2, fixed* u0, fixed *u1 ) const
{
	ShortestVectorToSegment( this->m_v0, this->m_v1, s2.m_v0, s2.m_v1, c1, c2, u0, u1 );
}


inline
CLineSegment3d& CLineSegment3d::operator=( const fixed* ijk )
{ 
	m_v0.m_i = *ijk; 
	m_v0.m_j = *( ijk + 1 );
	m_v0.m_k = *( ijk + 2 );
	m_v1.m_i = *( ijk + 3 ); 
	m_v1.m_j = *( ijk + 4 );
	m_v1.m_k = *( ijk + 5 );

	return *this;
}


inline
CLineSegment3d& CLineSegment3d::operator=( const CVector3d* v )
{ 
	m_v0 = *v; 
	m_v1 = *( v + 1 ); 
	return *this;
}


inline
fixed& CLineSegment3d::operator[]( uint32 idx )
{
	ASSERT( idx < 6 );

	return *( ( (fixed*)this ) + idx );
}


 

#endif // __CLINESEGMENT3D_H__